package com.xcm.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.util.ClassUtils;


/**
 * 
 * <p>Title: BeanUtils</p>  
 * <p>Description: </p>  
 * @author huangf 
 * @date 2018年4月19日
 */
public class BeanUtils {

	/**
	 * @param dest
	 * @param source
	 * @param ignoreNullValue
	 * @throws Exception
	 */
	public static void copyProperties(Object dest,
			Object source, boolean ignoreNullValue) {
		try {
			BeanInfo destBean = Introspector.getBeanInfo(dest.getClass());
			BeanInfo sourceBean = Introspector.getBeanInfo(source.getClass());
			PropertyDescriptor[] destPds = destBean.getPropertyDescriptors();
			PropertyDescriptor[] sourcePds = sourceBean.getPropertyDescriptors();
			for(PropertyDescriptor targetPd : destPds) {
				Method writeMethod = targetPd.getWriteMethod();
				if(writeMethod != null) {
					PropertyDescriptor sourcePd = getPropertyDescriptor(sourcePds, targetPd.getName());
					if (sourcePd != null) {
						Method readMethod = sourcePd.getReadMethod();
						if (readMethod != null &&
								ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
							try {
								if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
									readMethod.setAccessible(true);
								}
								Object value = readMethod.invoke(source);
								if(!ignoreNullValue || value != null) {
									if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
										writeMethod.setAccessible(true);
									}
									writeMethod.invoke(dest, value);
								}
							} catch (Throwable ex) {
								throw new IllegalStateException(
										"Could not copy property '" + targetPd.getName() + "' from source to target", ex);
							}
						}
					}
				}
			}
		} catch (Exception e) {
			throw new IllegalStateException("Could not copy from source to target",e);
		}
	}

	public static Map<String, Object> bean2Map(Object obj, boolean ignoreNullValue) {  
        if(obj == null){
            return null;  
        }
        Map<String, Object> map = new HashMap<String, Object>();  
        try {  
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());  
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();  
            for (PropertyDescriptor property : propertyDescriptors) {  
                String key = property.getName();  
                if (!key.equals("class")) {  
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);  
                    if(ignoreNullValue&&value==null)continue;
                    map.put(key, value);  
                }  
            }  
        } catch (Exception e) {  
        	throw new RuntimeException(e.getMessage(), e);
        }  
        return map;  
  
    }  
	
	
	public static Map<String, String> bean2MapNew(Object obj) {  
        if(obj == null){
            return null;  
        }
        Map<String, String> map = new HashMap<String, String>();  
        try {  
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());  
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();  
            for (PropertyDescriptor property : propertyDescriptors) {  
                String key = property.getName();  
                if (!key.equals("class")) {  
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);  
                    map.put(key,value==null?null: value.toString());  
                }  
            }  
        } catch (Exception e) {  
        	throw new RuntimeException(e.getMessage(), e);
        }  
        return map;  
  
    }  
	
	public static Map<String, String> bean2StringMap(Object obj) {  
        if(obj == null){
            return null;  
        }
        Map<String, String> map = new HashMap<String, String>();  
        try {  
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());  
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();  
            for (PropertyDescriptor property : propertyDescriptors) {  
                String key = property.getName();  
                if (!key.equals("class")) {  
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);  
                    map.put(key, value==null?"":String.valueOf(value));  
                }  
            }  
        } catch (Exception e) {  
        	throw new RuntimeException(e.getMessage(), e);
        }  
        return map;  
  
    }  
	public static Map<String, Object> bean2Map(Object obj) {  
		return bean2Map(obj,false);
		
	}  
	
	private static PropertyDescriptor getPropertyDescriptor(
			PropertyDescriptor[] pds, String name) throws IntrospectionException {
		for(PropertyDescriptor pd : pds) {
			if(name.equals(pd.getName())) {
				return pd;
			}
		}
		return null;
	}
	
	/**
	 * 属性相同的javabean复制值给另一个javabean
	 * 此方法将调用obj1的getter方法，将得到的值作为相应的参数传给obj2的setter方法,注意:obj1的getter方法和obj2方法必须是public类型
	 * @comment: <p>please description this method to do</p>  
	 * @create.date: 2016年4月21日 ( 下午3:04:22 )
	 * @author: zhangx
	 * @param obj1  被复制javabean
	 * @param obj2 复制javabean
	 * @return
	 * @throws Exception
	 * @see: <h1>com.zimadai.home.external.web.DataForWangDai315Controller.CopyBeanToBean</h1>
	 * @modified.by: 唐成
	 * @modified.author:
	 * @modified.date: <modified date time>
	 */
	public static Object CopyBeanToBean(Object obj1,Object obj2){
		org.springframework.beans.BeanUtils.copyProperties(obj1, obj2);
		return obj2;
	}

    /**
     * 属性相同的javabean复制值给另一个javabean
     * 此方法将调用obj1的getter方法，将得到的值作为相应的参数传给obj2的setter方法,注意:obj1的getter方法和obj2方法必须是public类型
     * @comment: <p>please description this method to do</p>
     * @create.date: 2016年6月23日 ( 下午3:43:22 )
     * @author: 唐成
     * @param obj1  被复制javabean
     * @param obj2 复制javabean
     * @param ignore 忽略的成员变量
     * @return
     * @throws Exception
     * @see: <h1>com.zimadai.home.external.web.DataForWangDai315Controller.CopyBeanToBean</h1>
     * @modified.by: <if there modified by others,then write author name>
     * @modified.author:
     * @modified.date: <modified date time>
     */
    public static Object CopyBeanToBean(Object obj1,Object obj2, List<String> ignore){
    	if(ignore != null) {
    		String[] ignoreArr = new String[ignore.size()];
    		ignore.toArray(ignoreArr);
    		org.springframework.beans.BeanUtils.copyProperties(obj1, obj2, ignoreArr);
    	} else {
    		org.springframework.beans.BeanUtils.copyProperties(obj1, obj2);
    	}
        return obj2;
    }
}
